using System;
using System.Reflection;
using fitnesse.components;
using fitnesse.responders.run;
using fitnesse.responders.run.slimResponder;
using fitnesse.slimTables;
using fitnesse.testutil;
using fitnesse.wiki;
using java.util;

namespace FitNesse4Net
{
    public class DotNetHtmlSlimTestSystem : SlimTestSystem
    {
        public DotNetHtmlSlimTestSystem(WikiPage page, TestSystemListener listener)
            : base(page, listener)
        {
        }

        protected override TableScanner scanTheTables(PageData pageData)
        {
            return new HtmlTableScanner(pageData.getHtml());
        }

        protected override String createHtmlResults(SlimTable startWithTable, SlimTable stopBeforeTable)
        {
            replaceExceptionsWithLinks();
            evaluateTables();
            var exceptionsString = exceptions.toHtml();

            var startTable = (startWithTable != null) ? startWithTable.getTable() : null;
            var endTable = (stopBeforeTable != null) ? stopBeforeTable.getTable() : null;
            var testResultHtml = tableScanner.toHtml(startTable, endTable);

            return exceptionsString + testResultHtml;
        }

        protected override ExecutionLog createExecutionLog(string classPath, Descriptor descriptor)
        {
            var slimSocketField = typeof(SlimTestSystem).GetField("slimSocket", BindingFlags.Instance | BindingFlags.NonPublic);
            var slimCommandField = typeof(SlimTestSystem).GetField("slimCommand", BindingFlags.Instance | BindingFlags.NonPublic);
            var slimRunnerField = typeof(SlimTestSystem).GetField("slimRunner", BindingFlags.Instance | BindingFlags.NonPublic);

            var slimFlags = page.getData().getVariable("SLIM_FLAGS") ?? "";

            var slimSocket = getNextSlimSocket();
            slimSocketField.SetValue(this, slimSocket);

            var slimArguments = slimFlags + " " + slimSocket;
            var slimCommandPrefix = buildCommand(descriptor, classPath);

            var slimCommand = slimCommandPrefix + " " + slimArguments;
            slimCommandField.SetValue(this, slimCommand);

            CommandRunner slimRunner;
            if (fastTest)
            {
                slimRunner = new MockCommandRunner();
                slimRunnerField.SetValue(this, slimRunner);

                DotNetSlimService.Execute(new DotNetSlimFactory(), slimArguments);
            }
            else
            {
                slimRunner = new CommandRunner(slimCommand, "", createClasspathEnvironment(classPath));
            }

            return new ExecutionLog(page, slimRunner);
        }

        public override List getInstructions()
        {
            return base.getInstructions();
        }

        public override Map getInstructionResults()
        {
            return base.getInstructionResults();
        }

        public override List getExpectations()
        {
            return base.getExpectations();
        }

        public override List getTestTables()
        {
            return base.getTestTables();
        }

        public override void start()
        {
            base.start();
        }

        public override string runTestsAndGenerateHtml(PageData pageData)
        {
            return base.runTestsAndGenerateHtml(pageData);
        }

        public override void bye()
        {
            base.bye();
        }

        public override PageData getTestResults()
        {
            return base.getTestResults();
        }

        public override TestSummary getTestSummary()
        {
            return base.getTestSummary();
        }

        public override string getCommandLine()
        {
            return base.getCommandLine();
        }

        public override int getNextSlimSocket()
        {
            return base.getNextSlimSocket();
        }

        protected override void evaluateExpectations()
        {
            base.evaluateExpectations();
        }

        public override string getSymbol(string symbolName)
        {
            return base.getSymbol(symbolName);
        }

        public override void setSymbol(string symbolName, string value)
        {
            base.setSymbol(symbolName, value);
        }

        public override void addScenario(string scenarioName, ScenarioTable scenarioTable)
        {
            base.addScenario(scenarioName, scenarioTable);
        }

        public override ScenarioTable getScenario(string scenarioName)
        {
            return base.getScenario(scenarioName);
        }

        public override void addExpectation(SlimTable.Expectation e)
        {
            base.addExpectation(e);
        }

        public override bool isSuccessfullyStarted()
        {
            return base.isSuccessfullyStarted();
        }

        public override void kill()
        {
            base.kill();
        }

        protected override void evaluateTables()
        {
            base.evaluateTables();
        }

        protected override void replaceExceptionsWithLinks()
        {
            base.replaceExceptionsWithLinks();
        }

        public override Map getScenarios()
        {
            return base.getScenarios();
        }

        public override ExecutionLog getExecutionLog(string classPath, Descriptor descriptor)
        {
            return base.getExecutionLog(classPath, descriptor);
        }

        protected override string buildCommand(Descriptor descriptor, string classPath)
        {
            return base.buildCommand(descriptor, classPath);
        }

        public override void setFastTest(bool fastTest)
        {
            base.setFastTest(fastTest);
        }

        public override void acceptOutputFirst(string output)
        {
            base.acceptOutputFirst(output);
        }

        public override void testComplete(TestSummary testSummary)
        {
            base.testComplete(testSummary);
        }

        public override void exceptionOccurred(Exception e)
        {
            base.exceptionOccurred(e);
        }

        protected override Map createClasspathEnvironment(string classPath)
        {
            return base.createClasspathEnvironment(classPath);
        }
    }
}